package generator;

import generator.config.GeneratorConfig;
import generator.service.CodeGeneratorService;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Scanner;

/**
 * 代码生成器主程序
 * 独立项目，不依赖其他模块
 */
@Slf4j
public class CodeGeneratorApplication {

    public static void main(String[] args) {
        try {
            // 创建固定配置
            GeneratorConfig config = createFixedConfig();
            
            // 清空输出目录
            cleanOutputDirectory(config.getCode().getXmlOutputDir());
            
            // 检查输出目录是否存在
            if (!checkOutputDirectories(config)) {
                return;
            }
            
            Scanner scanner = new Scanner(System.in);
            
            System.out.println("=== JE-PDU代码生成器 ===");
            System.out.println("数据库URL: " + config.getDatabase().getUrl());
            System.out.println("实体类输出目录: " + config.getCode().getEntityOutputDir());
            System.out.println("Mapper输出目录: " + config.getCode().getMapperOutputDir());
            System.out.println("XML输出目录: " + config.getCode().getXmlOutputDir());
            System.out.println("Service输出目录: " + config.getCode().getServiceOutputDir());
            System.out.println("ServiceImpl输出目录: " + config.getCode().getServiceImplOutputDir());
            System.out.println("Controller输出目录: " + config.getCode().getControllerOutputDir());
            System.out.println("使用自定义注解: " + (config.getCode().isUseCustomEntityAnnotations() ? "是" : "否"));
            System.out.println("生成额外类: " + (config.getCode().isGenerateExtraClasses() ? "是" : "否"));
            System.out.println();
            
            System.out.print("请输入要生成代码的表名(多个表名用英文逗号分隔): ");
            String tableNames = scanner.nextLine().trim();
            
            if (tableNames.isEmpty()) {
                System.out.println("表名不能为空!");
                return;
            }
            
            System.out.println("正在生成代码，请稍候...");
            
            // 创建代码生成服务
            CodeGeneratorService generatorService = new CodeGeneratorService(config);
            generatorService.generateCode(tableNames.split(","));
            
            System.out.println("代码生成完成!");
        } catch (Exception e) {
            log.error("代码生成失败", e);
            System.err.println("代码生成失败: " + e.getMessage());
        }
    }
    
    /**
     * 清空指定目录下的所有文件
     * @param directoryPath 目录路径
     */
    private static void cleanOutputDirectory(String directoryPath) {
        if (directoryPath == null || directoryPath.trim().isEmpty()) {
            System.out.println("警告: 输出目录路径为空，无法清空!");
            return;
        }
        
        File directory = new File(directoryPath);
        if (!directory.exists()) {
            System.out.println("提示: 输出目录不存在: " + directoryPath);
            return;
        }
        
        if (!directory.isDirectory()) {
            System.out.println("错误: 输出路径不是一个目录: " + directoryPath);
            return;
        }
        
        System.out.println("正在清空目录: " + directoryPath);
        try {
            deleteDirectoryContents(directory.toPath());
            System.out.println("目录清空完成: " + directoryPath);
        } catch (IOException e) {
            System.out.println("清空目录失败: " + directoryPath + ", 错误: " + e.getMessage());
            log.error("清空目录失败: " + directoryPath, e);
        }
    }
    
    /**
     * 删除目录下的所有内容
     * @param directory 目录路径
     * @throws IOException IO异常
     */
    private static void deleteDirectoryContents(Path directory) throws IOException {
        Files.walk(directory)
            .filter(path -> !path.equals(directory)) // 不删除目录本身
            .sorted((a, b) -> b.compareTo(a)) // 先删除子文件再删除目录
            .forEach(path -> {
                try {
                    Files.delete(path);
                } catch (IOException e) {
                    System.out.println("删除文件/目录失败: " + path + ", 错误: " + e.getMessage());
                    log.error("删除文件/目录失败: " + path, e);
                }
            });
    }
    
    /**
     * 检查输出目录是否存在
     * @param config 配置信息
     * @return 目录都存在返回true，否则返回false
     */
    private static boolean checkOutputDirectories(GeneratorConfig config) {
        boolean allExists = true;
        
        // 检查实体类输出目录
        if (!checkDirectoryExists(config.getCode().getEntityOutputDir(), "实体类")) {
            allExists = false;
        }
        
        // 检查Mapper输出目录
        if (!checkDirectoryExists(config.getCode().getMapperOutputDir(), "Mapper接口")) {
            allExists = false;
        }
        
        // 检查XML输出目录
        if (!checkDirectoryExists(config.getCode().getXmlOutputDir(), "XML映射文件")) {
            allExists = false;
        }
        
        // 检查Service输出目录
        if (!checkDirectoryExists(config.getCode().getServiceOutputDir(), "Service接口")) {
            allExists = false;
        }
        
        // 检查Service实现类输出目录
        if (!checkDirectoryExists(config.getCode().getServiceImplOutputDir(), "Service实现类")) {
            allExists = false;
        }
        
        // 检查Controller输出目录
        if (!checkDirectoryExists(config.getCode().getControllerOutputDir(), "Controller")) {
            allExists = false;
        }
        
        return allExists;
    }
    
    /**
     * 检查单个目录是否存在
     * @param directoryPath 目录路径
     * @param directoryType 目录类型（用于提示）
     * @return 目录存在返回true，否则返回false
     */
    private static boolean checkDirectoryExists(String directoryPath, String directoryType) {
        if (directoryPath == null || directoryPath.trim().isEmpty()) {
            System.out.println("警告: " + directoryType + "输出目录未配置!");
            return false;
        }
        
        File directory = new File(directoryPath);
        if (!directory.exists()) {
            System.out.println("提示: " + directoryType + "输出目录不存在: " + directoryPath);
            return false;
        }
        
        if (!directory.isDirectory()) {
            System.out.println("错误: " + directoryType + "输出路径不是一个目录: " + directoryPath);
            return false;
        }
        
        return true;
    }
    
    /**
     * 创建固定配置
     */
    private static GeneratorConfig createFixedConfig() {
        GeneratorConfig config = new GeneratorConfig();
        
        // 数据库配置 - 写死在代码中
        GeneratorConfig.Database database = new GeneratorConfig.Database();
        database.setUrl("jdbc:mysql://120.48.14.237:3306/xjs_pdu?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false");
        database.setUsername("root");
        database.setPassword("41876443855");
        database.setDriverClassName("com.mysql.cj.jdbc.Driver");
        config.setDatabase(database);
        
        // 代码生成配置 - 写死在代码中
        GeneratorConfig.Code code = new GeneratorConfig.Code();
        code.setAuthor("xulei");
        // 设置为统一的输出目录
        code.setEntityOutputDir("E:\\codeSH");
        code.setMapperOutputDir("E:\\codeSH");
        code.setXmlOutputDir("E:\\codeSH");
        code.setServiceOutputDir("E:\\codeSH");
        code.setServiceImplOutputDir("E:\\codeSH");
        code.setControllerOutputDir("E:\\codeSH");
        // 新增配置项
        code.setEntitySuffix("Entity"); // 实体类后缀
        code.setEntitySuperClass("BaseExtendEntity.BaseExtendOrgEntity<String>"); // 实体类继承的父类
        code.setIgnoreFields("id,creator_time,creator_user_id,creator_user,last_modify_time,last_modify_user_id,last_modify_user,delete_mark,delete_time,delete_user_id,version,sort_code,enabled_mark,organize_id,organize,tenant_id,remark"); // 忽略的字段列表
        code.setUseCustomEntityAnnotations(true); // 是否使用自定义注解
        code.setGenerateExtraClasses(true); // 生成额外的类（VO、DTO、Pagination）
        
        // 包配置 - 设置为空字符串，不使用包结构
        GeneratorConfig.Package pkg = new GeneratorConfig.Package();
        pkg.setEntity(""); // 空字符串表示不使用包结构
        pkg.setMapper("");
        pkg.setXml("");
        pkg.setService("");
        pkg.setServiceImpl("");
        pkg.setController("");
        code.setPkg(pkg);
        
        config.setCode(code);
        
        return config;
    }
}